<!DOCTYPE html>
<head>
    <title>我的第7个vue程序</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <link href="../css/style.css" rel="stylesheet"> </head>
</head>
<body>
    
    <h3>组件基础</h3>
    <div id="components-demo">
        <button-counter></button-counter>
    </div>
    <br>


    <p>组件的复用</p>
    <div id="components-demo2">
        <button-counter></button-counter>
        <button-counter></button-counter>
        <button-counter></button-counter>
    </div>
    <br>

    <p>通过 Prop 向子组件传递数据</p>
    <div id = "d3">
        <!-- <blog-post title="my journey with vue"></blog-post>
        <blog-post title="bloggging with vue"></blog-post>
        <blog-post title="why vue is so fun"></blog-post> -->
        <blog-post  v-for="post in posts" v-bind:key="post.id"  v-bind:title="post.title"></blog-post>
    </div>
    <br>


    <p>单个根元素</p>
    <div id = "d4" class="blog-post">
        <h3>{{title}}</h3>
        <div v-html="content"></div>
    </div>
    <br>

    <!--看起来当组件变得越来越复杂的时候，我们的博文不只需要标题和内容，还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦：-->
    <p>复杂的自定义组件</p>
    <div id="d5">
    <mblog-post
    v-for="post in posts"
    v-bind:key="post.id"
    v-bind:title="post.title"
    v-bind:content="post.content"
    v-bind:publishedAt="post.publishedAt"
    v-bind:comments="post.comments">
    </mblog-post>
    </div>
    <br/>

    <!-- 所以是时候重构一下这个 <blog-post> 组件了，让它变成接受一个单独的 post prop：-->
    <P>重构blog-post组件</P>
    <div id="d6">
    <blog-post2
    v-for="post in posts"
    v-bind:key="post.id"
    v-bind:post="post">
    </blog-post2>
    </div>
    <br/>




    <P>监听子组件事件</P>
    <div id="d7">
        <div :style="{ fontSize: postFontSize + 'em' }">
            <blog-post3 v-for="item in posts" v-bind:key="item.id" v-bind:post="item" v-on:enlarge-text="postFontSize += 0.1"></blog-post3> 
            <!--有的时候用一个事件来抛出一个特定的值是非常有用的。例如我们可能想让 <blog-post> 组件决定它的文本要放大多少。这时可以使用 $emit 的第二个参数来提供这个值：

            <button v-on:click="$emit('enlarge-text', 0.1)">
            Enlarge text
            </button>

            然后当在父级组件监听这个事件的时候，我们可以通过 $event 访问到被抛出的这个值：

            <blog-post
            ...
            v-on:enlarge-text="postFontSize += $event"
            ></blog-post>

            或者，如果这个事件处理函数是一个方法：

            <blog-post
            ...
            v-on:enlarge-text="onEnlargeText"
            ></blog-post>
            -->
            <blog-post4 v-for="item in posts" v-bind:key="item.id" v-bind:post="item" v-on:enlarge-text="onEnlargeText"></blog-post4> 
        </div>
    </div>
    <br/>
   
    <P>在组件上使用v-model</P>
    <!-- 自定义事件也可以用于创建支持 v-model 的自定义输入组件。记住：

        <input v-model="searchText">

        等价于：

        <input
        v-bind:value="searchText"
        v-on:input="searchText = $event.target.value"
        >

        当用在组件上时，v-model 则会这样：
        <custom-input
        v-bind:value="searchText"
        v-on:input="searchText = $event"
        ></custom-input>

        为了让它正常工作，这个组件内的 <input> 必须：

        将其 value attribute 绑定到一个名叫 value 的 prop 上
        在其 input 事件被触发时，将新的值通过自定义的 input 事件抛出

-->
    <div id="d8">
        <custom-input v-bind:value="searchText" v-on:input="searchText=$event"></custom-input>
    </div>
    <br/><br/>


    
    <p>通过插槽分发内容</p>
    <div id="d9">
        <alert-box>有些事发生了。</alert-box>
    </div>
    <br/><br/>

    

    <p>动态组件</p>
    <div id="d10">
        <!-- 组件会在 `currentTabComponent` 改变时改变 
        在上述示例中，currentTabComponent 可以包括
        已注册组件的名字，或
        一个组件的选项对象

        
        -->
        <component v-bind:is="currentTabComponent"></component>
    </div>
    <br/><br/>
    
    <!--解析 DOM 模板时的注意事项
        有些 HTML 元素，诸如 <ul>、<ol>、<table> 和 <select>，对于哪些元素可以出现在其内部是有严格限制的。而有些元素，诸如 <li>、<tr> 和 <option>，只能出现在其它某些特定的元素内部。
        这会导致我们使用这些有约束条件的元素时遇到一些问题。例如：
        <table>
        <blog-post-row></blog-post-row>
        </table>

        这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部，并导致最终渲染结果出错。幸好这个特殊的 is attribute 给了我们一个变通的办法：

        <table>
        <tr is="blog-post-row"></tr>
        </table>

        需要注意的是如果我们从以下来源使用模板的话，这条限制是不存在的：

            字符串 (例如：template: '...')
            单文件组件 (.vue)
            <script type="text/x-template">
        到这里，你需要了解的解析 DOM 模板时的注意事项——实际上也是 Vue 的全部必要内容，大概就是这些了。恭喜你！接下来还有很多东西要去学习，不过首先，我们推荐你先休息一下，试用一下 Vue，自己随意做些好玩的东西。
        如果你感觉已经掌握了这些知识，我们推荐你再回来把完整的组件指南，包括侧边栏中组件深入章节的所有页面读完。
-->

</body>
<script>
    //一个组件的 data 选项必须是一个函数，因此每个实例可以维护一份被返回对象的独立的
    //注册了一个button-counter组件
    Vue.component('button-counter',{
        data:function(){
            return{
                count:0
            }
        },
        template:'<button v-on:click="count++"> You clicked me {{count}} </button>'
    })
    /**
     * 组件都通过 Vue.component 全局注册,
     * 全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例，也包括其组件树中的所有子组件的模板中。
     * 
    */
   var v1 = new Vue({
        el:'#components-demo'
    })

    var v2 = new Vue({
        el:'#components-demo2'
    })

    //通过props向子组件传递数据,通过props向template传递数据
    //单个根元素
    Vue.component('blog-post',{
        props:['title'],
        template:'<p>{{title}}</p>'
    })
    var v4 = new Vue({
        el:'#d4',
        data:{
            title:"haha",
            content:"hello world"
        }
    })


    Vue.component('mblog-post',{
        props:['title'],
        template:'<p>{{title}}</p>'
    })
     //复杂的自定义组件
    var v5 = new Vue({
        el:'#d5',
        data:{
            posts:[
                {id:1,title:'my journey with vue'},
                {id:2,title:'blogging with vue'},
                {id:3,title:'why vue is so fun'}
            ]
        }
    })

    Vue.component('blog-post2',{
        props:['post'],
        template:'<div class="blog-post"><p>{{post.title}}</p><div v-html="post.content"></div></div>'
    })

    var v6 = new Vue({
        el:'#d6',
        data:{
            posts:[
                {id:1,title:'my journey with vue',content:"java"},
                {id:2,title:'blogging with vue',content:"vue"},
                {id:3,title:'why vue is so fun',content:"js"}
            ]
        }
    })

    /**
     * 引号太多，使用\' 来转义，<button v-on:click="$emit('enlarge-text')"> 需要这样写，但是外面有一层引号
     * 
    */
   //监听子组件事件
    Vue.component('blog-post3',{
        props:['post'],
        template:'<div class=""><p>{{post.title}}</p><button v-on:click="$emit(\'enlarge-text\')">变大</button><div v-html="post.content"></div></div>'
    })
    //使用事件抛出一个值
    Vue.component('blog-post4',{
        props:['post'],
        template:'<div class=""><p>{{post.title}}</p><button v-on:click="$emit(\'enlarge-text\',0.1)">变大</button><div v-html="post.content"></div></div>'
    })
    var v7 = new Vue({
        el:'#d7',
        data:{
            postFontSize: 1 ,
            posts:[
                {id:1,title:'my journey with vue',content:"java"}
            ]
        },
        methods:{
            onEnlargeText:function(enlargeAmount){
                this.postFontSize += enlargeAmount
            }
        }
    })

    //在组件上使用 v-model
    Vue.component('custom-input',{
        props:['value'],
        template:'<input v-bind:value="value" v-on:input="$emit(\'input\',$event.target.value)">'
    })
    var v8 = new Vue({
        el:'#d8',
        data:{
            searchText:""
        }
    })
    
    //通过插槽分发内容, 自定义组件的内容在原有标签的前面
    //Error!有些事发生了。
    Vue.component('alert-box',{
        template:'<div class=""><strong>Error!</strong><slot></slot></div>'
    })
    var v9 = new Vue({
        el:'#d9',
        data:{}
    })


   




</script>


</html>